local PIANO = {
    2878, 2879, 2880, 2881, 2882, 2883, 2884, 2885, 2886, 2887, 2888, 2889,
    0862, 0863, 0864, 0865, 0866, 0867, 0868, 0869, 0870, 0871, 0872, 0873,
    0874, 0875, 0876, 0877, 0878, 0879, 0880, 0881, 0882, 0883, 0884, 0885,
    0886, 0887, 0888, 0889, 0890, 0891, 0892, 0893, 0894, 0895, 0896, 0897,
    0898, 2890, 2891, 2892, 2893, 2894, 2895, 2896, 2897, 2898, 2899, 2900, 2901
} ---@type SoundKey[]

local GUITAR = {
    3024, 3025, 3026, 3027, 3028, 3029, 3030, 3031, 3032, 3033, 3034, 3035,
    3036, 3037, 3038, 3039, 3040, 3041, 3042, 3043, 3044, 3045, 3046, 3047,
    3048, 3049, 3050, 3051, 3052, 3053, 3054, 3055, 3056, 3057, 3058, 3059,
    3060, 3061, 3062, 3063, 3064, 3065, 3066, 3067, 3068, 3069, 3070, 3071,
    3072, 3073, 3074, 3075, 3076, 3077, 3078, 3079, 3080, 3081, 3082, 3083, 3092
} ---@type SoundKey[]

local BRASS = {
    2963, 2964, 2965, 2966, 2967, 2968, 2969, 2970, 2971, 2972, 2973, 2974,
    2975, 2976, 2977, 2978, 2979, 2980, 2981, 2982, 2983, 2984, 2985, 2986,
    2987, 2988, 2989, 2990, 2991, 2992, 2993, 2994, 2995, 2996, 2997, 2998,
    2999, 3000, 3001, 3002, 3003, 3004, 3005, 3006, 3007, 3008, 3009, 3010,
    3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019, 3020, 3021, 3022, 3023
} ---@type SoundKey[]

local STRING = {
    2902, 2903, 2904, 2905, 2906, 2907, 2908, 2909, 2910, 2911, 2912, 2913,
    2914, 2915, 2916, 2917, 2918, 2919, 2920, 2921, 2922, 2923, 2924, 2925,
    2926, 2927, 2928, 2929, 2930, 2931, 2932, 2933, 2934, 2935, 2936, 2937,
    2938, 2939, 2940, 2941, 2942, 2943, 2944, 2945, 2946, 2947, 2948, 2949,
    2950, 2951, 2952, 2953, 2954, 2955, 2956, 2957, 2958, 2959, 2960, 2961, 2962
} ---@type SoundKey[]

local ELEC_BASS = {
    0788, 0789, 0790, 0791, 0792, 0793, 0794, 0795, 0796, 0797, 0798, 0799,
    0800, 0801, 0802, 0803, 0804, 0805, 0806, 0807, 0808, 0809, 0810, 0811,
    0812, 0813, 0814, 0815, 0816, 0817, 0818, 0819, 0820, 0821, 0822, 0823,
    0824
} ---@type SoundKey[]

local ELEC_GUITAR_1 = {
    0677, 0678, 0679, 0680, 0681, 0682, 0683, 0684, 0685, 0686, 0687, 0688,
    0689, 0690, 0691, 0692, 0693, 0694, 0695, 0696, 0697, 0698, 0699, 0700,
    0701, 0702, 0703, 0704, 0705, 0706, 0707, 0708, 0709, 0710, 0711, 0712,
    0713
} ---@type SoundKey[]

local ELEC_GUITAR_2 = {
    0714, 0715, 0716, 0717, 0718, 0719, 0720, 0721, 0722, 0723, 0724, 0725,
    0726, 0727, 0728, 0729, 0730, 0731, 0732, 0733, 0734, 0735, 0736, 0737,
    0738, 0739, 0740, 0741, 0742, 0743, 0744, 0745, 0746, 0747, 0748, 0749,
    0750
} ---@type SoundKey[]

local ELEC_GUITAR_3 = {
    0751, 0752, 0753, 0754, 0755, 0756, 0757, 0758, 0759, 0760, 0761, 0762,
    0763, 0764, 0765, 0766, 0767, 0768, 0769, 0770, 0771, 0772, 0773, 0774,
    0775, 0776, 0777, 0778, 0779, 0780, 0781, 0782, 0783, 0784, 0785, 0786,
    0787
} ---@type SoundKey[]

local DRUMKIT = {
    899, 900, 901, 902, 903
} ---@type SoundKey[]

local STANDAR_DRUMKIT = {
    [42 - 1] = 910,
    [41 - 1] = 903,
    [40 - 1] = 901,
    [39 - 1] = 916,
    [38 - 1] = 905,
    [37 - 1] = 5091,
    [36 - 1] = 899,
    [35 - 1] = 5138,
} ---@type table<integer, SoundKey>

---@class Midi
---@field sound_effect SoundKey[]
---@field source string
---@field listeners Role[]
---@field speed Fixed
---@field track_name string
---@field volume_rate Fixed
---@field is_main boolean
---@field continue boolean
---@field delay Fixed
local Midi = {}
Midi.__index = Midi

--- 构造一个Midi实例
---@param sound_effect string | "PIANO" | "GUITAR" | "BRASS" | "STRING" | "DRUMKIT" | "ELEC_BASS" | "ELEC_GUITAR_1" | "ELEC_GUITAR_2" | "ELEC_GUITAR_3" | "STANDAR_DRUMKIT" 音效
function Midi.create(sound_effect, path, track_name)
    local self = setmetatable({}, Midi)
    if sound_effect == "PIANO" then
        self.sound_effect = PIANO
    elseif sound_effect == "GUITAR" then
        self.sound_effect = GUITAR
    elseif sound_effect == "BRASS" then
        self.sound_effect = BRASS
    elseif sound_effect == "STRING" then
        self.sound_effect = STRING
    elseif sound_effect == "DRUMKIT" then
        self.sound_effect = DRUMKIT
    elseif sound_effect == "STANDAR_DRUMKIT" then
        self.sound_effect = STANDAR_DRUMKIT
    elseif sound_effect == "ELEC_BASS" then
        self.sound_effect = ELEC_BASS
    elseif sound_effect == "ELEC_GUITAR_1" then
        self.sound_effect = ELEC_GUITAR_1
    elseif sound_effect == "ELEC_GUITAR_2" then
        self.sound_effect = ELEC_GUITAR_2
    elseif sound_effect == "ELEC_GUITAR_3" then
        self.sound_effect = ELEC_GUITAR_3
    else
        self.sound_effect = {} ---@type SoundKey[]
    end
    self.track_name = track_name
    self.is_main = GlobalAPI.str_contains(track_name, "main")
    self.listeners = {}
    self.source = require("midi@" .. path .. "_" .. track_name)
    self.volume_rate = 1.0
    self.speed = 1.0
    self.continue = true
    return self
end

---@param delay Fixed
function Midi:play(delay)
    self.delay = delay
    self:play_next(0)
end

---播放下一迭代
---@param order integer
function Midi:play_next(order)
    if order * 9 + 1 >= #self.source then return end
    local note     = math.tointeger(string.sub(self.source, order * 9 + 1, (order + 1) * 9)) or 0
    local tone     = note // 10000000
    local duration = note // 100000 % 100
    local velocity = note // 1000 % 100
    local interval = math.tointeger(math.tofixed(note % 1000) * self.speed) or 0
    local function play_sound()
        LuaAPI.call_delay_time(self.delay, function()
            ---@param player Role
            for _, player in ipairs(self.listeners) do
                player.get_ctrl_unit().play_3d_sound(
                    self.sound_effect[tone + 1] or 0,
                    math.tofixed(duration) / 30.0,
                    math.tofixed(velocity) * self.volume_rate
                )
            end
        end)
        if self.is_main then
            LuaAPI.global_send_event({ EVENT.CUSTOM_EVENT, "接收音符" }, { ["TONE"] = tone })
        end
        self:play_next(order + 1)
    end
    if interval == 0 and self.continue then
        play_sound()
    elseif self.continue then
        LuaAPI.call_delay_frame(interval, function()
            play_sound()
        end)
    end
    self.order = order + 1
end

function Midi:pause()
    self.continue = false
end

function Midi:resume()
    self.continue = true
    self:play_next(self.order)
end

---添加玩家
---@param player Role
function Midi:add_player(player)
    table.insert(self.listeners, player)
end

---设置倍速
---@param speed Fixed
function Midi:set_speed(speed)
    self.speed = 1.0 / speed
end

---设置声音比例
---@param volume_rate Fixed
function Midi:set_volume_rate(volume_rate)
    self.volume_rate = volume_rate
end

function Midi:destroy()
    self.play_next = nil
    self.set_volume_rate = nil
    self.set_speed = nil
    self.add_player = nil
    self.pause = nil
    self.play = nil
    self.continue = nil
    self.speed = nil
    self.order = nil
    self.listeners = nil
    self.is_main = nil
    self.volume_rate = nil
    self.track_name = nil
    self.sound_effect = nil
    self.source = nil
end

return Midi
